import 'dart:ui';

import 'package:flutter/material.dart';

///组合动画用法
///
///抽奖滚动动画 stack的组合
///
///
///
///

class PointOffset {
  Offset point;
  bool isEnd;
  static List<PointOffset> _pointOffset = <PointOffset>[];

  PointOffset.name(this.point, this.isEnd);
}

class CanvasPointScroll2 extends StatefulWidget {
  @override
  _CanvasPointScrollState2 createState() => _CanvasPointScrollState2();
}

class _CanvasPointScrollState2 extends State<CanvasPointScroll2> {
  //布局
  final GlobalKey containWidgetGlobalKey = GlobalKey();

  var _scrollController = ScrollController();

  //画布
  late BoardPainterWidget canvasWidget;

  //局部刷新
  late CounterNotify counterNotify;

  @override
  void initState() {
    super.initState();
    counterNotify = CounterNotify();

    Future.delayed(Duration(milliseconds: 5000), () {
      counterNotify.addValue(400);
    });

    canvasWidget = BoardPainterWidget(containWidgetGlobalKey);
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: SingleChildScrollView(
          controller: _scrollController,
          child: Stack(
            children: [
              Column(
                key: containWidgetGlobalKey,
                children: [
                  Container(
                    color: Color(0xFF15C9E8),
                    width: 100,
                    height: 400,
                  ),
                  Container(
                    color: Color(0xFF300C92),
                    width: 400,
                    height: 400,
                  ),
                  Container(
                    color: Color(0xFFB41C89),
                    width: 400,
                    height: 400,
                  ),
                  TextButton(
                      onPressed: () {
                        print("按钮");
                      },
                      child: Text("data")),
                  TextField(),
                  ValueListenableBuilder<double>(
                    builder: (BuildContext context, value, Widget? child) {
                      return Container(
                        color: Color(0xFF1947EE),
                        width: 400,
                        height: value,
                      );
                    },
                    valueListenable: counterNotify.countListenable,
                  )
                ],
              ),
              canvasWidget
            ],
          ),
        ),
      ),
    );
  }
}

class CounterNotify with ChangeNotifier {
  ValueNotifier<double> _countListenable = ValueNotifier<double>(0.0);

  ValueNotifier<double> get countListenable => _countListenable;

  void addValue(double i) {
    _countListenable.value += i;
  }
}

class BoardPainterWidget extends StatefulWidget {
  GlobalKey containWidgetGlobalKey;

  BoardPainterWidget(this.containWidgetGlobalKey);

  // void Function(double move)? callMoveBack;

  // void getMoveDistance(double move){
  //    print("getMoveDistance--:$move");
  //    _state.getMoveDistance(move);
  // }

  _BoardPainterWidgetState _state = _BoardPainterWidgetState();

  @override
  _BoardPainterWidgetState createState() {
    return _state;
  }
}

class _BoardPainterWidgetState extends State<BoardPainterWidget> {
  /// 已描绘的点
  List<PointOffset> _pointOffset = <PointOffset>[];

  final GlobalKey containWidgetGlobalKey = GlobalKey();

  //一屏的高度
  double screenHeight = 0;

  //画布的高度
  double _gestureDetectorHeight = 0;

  late ValueNotifier<List<PointOffset>> _pointListenable;

  /// 添加点，注意不要超过Widget范围
  _addPoint(DragUpdateDetails details) {
    Size? referenceBox = widget.containWidgetGlobalKey.currentContext?.size;
    double maxW = referenceBox?.width ?? 0;
    double maxH = referenceBox?.height ?? 0;
    // 校验范围
    if (details.localPosition.dx <= 0 || details.localPosition.dy <= 0) return;
    if (details.localPosition.dx > maxW || details.localPosition.dy > maxH)
      return;

    // print("_addPoint $_gestureDetectorHeight");
    // setState(() {
    //   _pointOffset = List.from(_pointOffset)
    //     ..add(PointOffset.name(details.localPosition, true));
    // });
    //listener监听，不会影响整棵树的绘制
    _pointOffset = List.from(_pointOffset)
      ..add(PointOffset.name(details.localPosition, true));
    _pointListenable.value = _pointOffset;
  }

  void moveCallback(double move) {}

  @override
  void initState() {
    super.initState();
    _pointListenable = ValueNotifier<List<PointOffset>>(_pointOffset);

    WidgetsBinding.instance?.addPostFrameCallback((_) {
      _gestureDetectorHeight =
          widget.containWidgetGlobalKey.currentContext?.size?.height ?? 0;
      print("绘制完成1：$_gestureDetectorHeight");
      WidgetsBinding.instance?.addPersistentFrameCallback((_) {
        // print("实时Frame绘制回调"); //每帧都回调
        var widgetHeight =
            widget.containWidgetGlobalKey.currentContext?.size?.height ?? 0;
        if (widgetHeight != _gestureDetectorHeight &&
            widgetHeight > _gestureDetectorHeight) {
          _gestureDetectorHeight = widgetHeight;
          setState(() {});
          print("绘制完成2：$_gestureDetectorHeight");
        }
      });

      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Container(
          child: GestureDetector(
            onTap: () {
              print("GestureDetector 点击");
            },
            onHorizontalDragUpdate: (details) => _addPoint(details),
            onHorizontalDragEnd: (details) {
              // print("绘制 onPanEnd");
              _pointOffset.add(PointOffset.name(Offset.zero, false));
              // _points.add(Offset.zero);
            },
          ),
          height: _gestureDetectorHeight,
        ),
        RepaintBoundary(
            //隔离重绘控件，singlescrollview 滑动发生重绘，导致画笔paint响应
            child: CustomPaint(
                painter: BoardPainter(
                    points: _pointOffset, factor: _pointListenable))),
      ],
    );
  }
}

class BoardPainter extends CustomPainter {
  final ValueNotifier<List<PointOffset>>? factor;

  BoardPainter({required this.points, this.factor}) : super(repaint: factor);

  List<PointOffset> points;

  void paint(Canvas canvas, Size size) {
    points = factor?.value ?? points;
    // print("绘制 paint1 ${points.length}-- ${factor?.value.length}");
    if (points == null) {
      return;
    }
    Paint paint = Paint()
      ..color = Colors.black
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 5.0;
    for (int i = 0; i < points.length - 1; i++) {
      if (points[i] != null &&
          points[i + 1] != null &&
          points[i + 1].isEnd &&
          points[i].isEnd) {
        // print("绘制 paint${points[i].point}----${points[i + 1].point}");

        canvas.drawLine(points[i].point, points[i + 1].point, paint);
      }
    }
  }

  bool shouldRepaint(BoardPainter other) {
    // print("绘制 shouldRepaint--:${other.points != points}");
    return other.points != points;
  }
}
